#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include "stm32mp157_rcc.h"
#include "stm32mp157_gpio.h"
#include "led_plat.h"

#define RCC_START       RCC
#define RCC_END         (RCC + sizeof(rcc_t) - 1)
#define GPIOZ_START     GPIOZ
#define GPIOZ_END       (GPIOZ + sizeof(gpio_t) - 1)
#define GPIOE_START     GPIOE
#define GPIOE_END       (GPIOE + sizeof(gpio_t) - 1)
#define GPIOF_START     GPIOF
#define GPIOF_END       (GPIOF + sizeof(gpio_t) - 1)

struct led_plat_data led_data[] = {
	//GPIOZ -5
	[0] = {
			//哪个灯
			.led_name = "stm32mp157_led_drv1",
			//设备节点
			.dev_name = "led_drv1",
			//次设备号
			.minor = 1,
			//RCC
			.RCC_PLL4CR_SET = (1 << 0),
			.RCC_PLL4CR_TEST = (1 << 1),
			.RCC_MP_AHB4ENSETR_SET = (1 << 4) | (1 << 5),
			//GPIOZ
			.GPIO_MODER_RESET = ~(0x03 << 10),
			.GPIO_MODER_SET = (0x01 << 10),
			.GPIO_OTYPER_RESET = ~(0x01 << 5),
			.GPIO_OSPEEDR_RESET = ~(0x03 << 10),
			.GPIO_ODR_RESET = ~(0x01 << 5),
			.GPIO_ODR_SET = (0x01 << 5),
	},
	//GPIOZ -6
	[1] = {
			//哪个灯
			.led_name = "stm32mp157_led_drv2",
			//设备节点
			.dev_name = "led_drv2",
			//次设备号
			.minor = 2,
			//RCC
			.RCC_PLL4CR_SET = (1 << 0),
			.RCC_PLL4CR_TEST = (1 << 1),
			.RCC_MP_AHB4ENSETR_SET = (1 << 4) | (1 << 5),
			//GPIOZ
			.GPIO_MODER_RESET = ~(0x03 << 12),
			.GPIO_MODER_SET = (0x01 << 12),
			.GPIO_OTYPER_RESET = ~(0x01 << 6),
			.GPIO_OSPEEDR_RESET = ~(0x03 << 12),
			.GPIO_ODR_RESET = ~(0x01 << 6),
			.GPIO_ODR_SET = (0x01 << 6),
	},
	//GPIOZ -7
	[2] = {
			//哪个灯
			.led_name = "stm32mp157_led_drv3",
			//设备节点
			.dev_name = "led_drv3",
			//次设备号
			.minor = 3,
			//RCC
			.RCC_PLL4CR_SET = (1 << 0),
			.RCC_PLL4CR_TEST = (1 << 1),
			.RCC_MP_AHB4ENSETR_SET = (1 << 4) | (1 << 5),
			//GPIOZ
			.GPIO_MODER_RESET = ~(0x03 << 14),
			.GPIO_MODER_SET = (0x01 << 14),
			.GPIO_OTYPER_RESET = ~(0x01 << 7),
			.GPIO_OSPEEDR_RESET = ~(0x03 << 14),
			.GPIO_ODR_RESET = ~(0x01 << 7),
			.GPIO_ODR_SET = (0x01 << 7),
	},
	//GPIOE-8
	[3] = {
			//哪个灯
			.led_name = "stm32mp157_led_drv4",
			//设备节点
			.dev_name = "led_drv4",
			//次设备号
			.minor = 4,
			//RCC
			.RCC_PLL4CR_SET = (1 << 0),
			.RCC_PLL4CR_TEST = (1 << 1),
			.RCC_MP_AHB4ENSETR_SET = (1 << 4) | (1 << 5),
			//GPIOZ
			.GPIO_MODER_RESET = ~(0x03 << 16),
			.GPIO_MODER_SET = (0x01 << 16),
			.GPIO_OTYPER_RESET = ~(0x01 << 8),
			.GPIO_OSPEEDR_RESET = ~(0x03 << 16),
			.GPIO_ODR_RESET = ~(0x01 << 8),
			.GPIO_ODR_SET = (0x01 << 8),
	},
	//GPIOE-10
	[4] = {
			//哪个灯
			.led_name = "stm32mp157_led_drv5",
			//设备节点
			.dev_name = "led_drv5",
			//次设备号
			.minor = 5,
			//RCC
			.RCC_PLL4CR_SET = (1 << 0),
			.RCC_PLL4CR_TEST = (1 << 1),
			.RCC_MP_AHB4ENSETR_SET = (1 << 4) | (1 << 5),
			//GPIOZ
			.GPIO_MODER_RESET = ~(0x03 << 20),
			.GPIO_MODER_SET = (0x01 << 20),
			.GPIO_OTYPER_RESET = ~(0x01 << 10),
			.GPIO_OSPEEDR_RESET = ~(0x03 << 20),
			.GPIO_ODR_RESET = ~(0x01 << 10),
			.GPIO_ODR_SET = (0x01 << 10),
	},
	//GPIOF-10
	[5] = {
			//哪个灯
			.led_name = "stm32mp157_led_drv6",
			//设备节点
			.dev_name = "led_drv6",
			//次设备号
			.minor = 6,
			//RCC
			.RCC_PLL4CR_SET = (1 << 0),
			.RCC_PLL4CR_TEST = (1 << 1),
			.RCC_MP_AHB4ENSETR_SET = (1 << 4) | (1 << 5),
			//GPIOZ
			.GPIO_MODER_RESET = ~(0x03 << 20),
			.GPIO_MODER_SET = (0x01 << 20),
			.GPIO_OTYPER_RESET = ~(0x01 << 10),
			.GPIO_OSPEEDR_RESET = ~(0x03 << 20),
			.GPIO_ODR_RESET = ~(0x01 << 10),
			.GPIO_ODR_SET = (0x01 << 10),
	},
};


struct resource	led_res[][2] = {
	//GPIOZ -5
	[0] = {
		[0] = {
			.start = RCC_START,
			.end = RCC_END,
			.name = "rcc",
			.flags = IORESOURCE_MEM,
		},
		[1] = {
			.start = GPIOZ_START,
			.end = GPIOZ_END,
			.name = "gpioz",
			.flags = IORESOURCE_MEM,
		},
	},
	//GPIOZ -6
	[1] = {
		[0] = {
			.start = RCC_START,
			.end = RCC_END,
			.name = "rcc",
			.flags = IORESOURCE_MEM,
		},
		[1] = {
			.start = GPIOZ_START,
			.end = GPIOZ_END,
			.name = "gpioz",
			.flags = IORESOURCE_MEM,
		},
	},
	//GPIOZ -7
	[2] = {
		[0] = {
			.start = RCC_START,
			.end = RCC_END,
			.name = "rcc",
			.flags = IORESOURCE_MEM,
		},
		[1] = {
			.start = GPIOZ_START,
			.end = GPIOZ_END,
			.name = "gpioz",
			.flags = IORESOURCE_MEM,
		},
	},
	//GPIOE - 8
	[3] = {
		[0] = {
			.start = RCC_START,
			.end = RCC_END,
			.name = "rcc",
			.flags = IORESOURCE_MEM,
		},
		[1] = {
			.start = GPIOE_START,
			.end = GPIOE_END,
			.name = "gpioe",
			.flags = IORESOURCE_MEM,
		},
	},
	//GPIOE - 10
	[4] = {
		[0] = {
			.start = RCC_START,
			.end = RCC_END,
			.name = "rcc",
			.flags = IORESOURCE_MEM,
		},
		[1] = {
			.start = GPIOE_START,
			.end = GPIOE_END,
			.name = "gpioe",
			.flags = IORESOURCE_MEM,
		},
	},
	//GPIOF - 10
	[5] = {
		[0] = {
			.start = RCC_START,
			.end = RCC_END,
			.name = "rcc",
			.flags = IORESOURCE_MEM,
		},
		[1] = {
			.start = GPIOF_START,
			.end = GPIOF_END,
			.name = "gpiof",
			.flags = IORESOURCE_MEM,
		},
	},
};

void led_dev_release(struct device *dev)
{
}

struct platform_device led_dev[] = {
    //GPIOZ -5
	[0] = {
		.name = "stm32mp157_led1", //名称
		.id = 1, //ID用来区分每个设备
		.dev = {
			.release = led_dev_release,
			.platform_data = &led_data[0], 
		},
		.num_resources = ARRAY_SIZE(led_res[0]),//资源个数
		.resource = led_res[0],//资源的起始地址
	},
	//GPIOZ -6
	[1] = {
		.name = "stm32mp157_led2", //名称
		.id = 2, //ID用来区分每个设备
		.dev = {
			.release = led_dev_release,
			.platform_data = &led_data[1], 
		},
		.num_resources = ARRAY_SIZE(led_res[1]),//资源个数
		.resource = led_res[1],//资源的起始地址
	},
	//GPIOZ -7
	[2] = {
		.name = "stm32mp157_led3", //名称
		.id = 3, //ID用来区分每个设备
		.dev = {
			.release = led_dev_release,
			.platform_data = &led_data[2], 
		},
		.num_resources = ARRAY_SIZE(led_res[2]),//资源个数
		.resource = led_res[2],//资源的起始地址
	},
	//GPIOE -8
	[3] = {
		.name = "stm32mp157_led4", //名称
		.id = 4, //ID用来区分每个设备
		.dev = {
			.release = led_dev_release,
			.platform_data = &led_data[3], 
		},
		.num_resources = ARRAY_SIZE(led_res[3]),//资源个数
		.resource = led_res[3],//资源的起始地址
	},
	//GPIOE -10
	[4] = {
		.name = "stm32mp157_led5", //名称
		.id = 5, //ID用来区分每个设备
		.dev = {
			.release = led_dev_release,
			.platform_data = &led_data[4], 
		},
		.num_resources = ARRAY_SIZE(led_res[4]),//资源个数
		.resource = led_res[4],//资源的起始地址
	},
	//GPIOF -10
	[5] = {
		.name = "stm32mp157_led6", //名称
		.id = 6, //ID用来区分每个设备
		.dev = {
			.release = led_dev_release,
			.platform_data = &led_data[5], 
		},
		.num_resources = ARRAY_SIZE(led_res[5]),//资源个数
		.resource = led_res[5],//资源的起始地址
	},

};

static int __init led_dev_init(void)
{
	int i;
	int ret;
	for(i = 0; i < ARRAY_SIZE(led_dev); i++)
	{
		ret = platform_device_register(&led_dev[i]);
		if(ret < 0)
		{
			printk("platform_device_register error\n");
			goto platform_device_register_err;
		}
	}
	return 0;
	platform_device_register_err:
		for(;i>0;i--)
		{
			platform_device_unregister(&led_dev[i-1]);
		}
	return ret;
}

static void __exit led_dev_exit(void)
{
	int i;
	for(i = 0; i < ARRAY_SIZE(led_dev); i++)
	{
		platform_device_unregister(&led_dev[i]);
	}
}

module_init(led_dev_init);
module_exit(led_dev_exit);
MODULE_LICENSE("GPL");

